package com.dominator.serviceImpl;

import com.dominFramework.core.id.SystemIdUtils;
import com.dominFramework.core.typewrap.Dto;
import com.dominFramework.core.typewrap.Dtos;
import com.dominFramework.core.utils.SystemUtils;
import com.dominator.enums.ReqEnums;
import com.dominator.mybatis.dao.*;
import com.dominator.repository.*;
import com.dominator.service.*;
import com.dominator.socket.WebSocketTools;
import com.dominator.utils.api.ApiMessage;
import com.dominator.utils.api.ApiMessageUtil;
import com.dominator.utils.api.ApiUtils;
import com.dominator.utils.dao.RedisUtil;
import com.dominator.utils.encode.Des3Utils;
import com.dominator.utils.exception.ApiException;
import com.dominator.utils.jpush.JpushClientUtil;
import com.dominator.utils.qiniu.QiniuUploadFile;
import com.dominator.utils.system.PrimaryGenerater;
import com.dominator.utils.system.PropertiesLoader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("ApiMachineService")
public class ApiMachineServiceImpl implements ApiMachineService {

    @Autowired
    T_machineDao tMachineDao;
    @Autowired
    T_game_priceDao tGamePriceDao;
    @Autowired
    T_shopDao tShopDao;
    @Autowired
    T_machine_loginDao tMachineLoginDao;
    @Autowired
    DaoGame daoGame;
    @Autowired
    DaoGamePrice daoGamePrice;

    @Autowired
    T_userDao tUserDao;
    @Autowired
    DaoAccount daoAccount;
    @Autowired
    DaoMachine daoMachine;
   @Autowired
    DaoBigReward daoBigReward;
   @Autowired
   DaoMachineLogin daoMachineLogin;





    @Autowired
    ApiOrderService apiOrderService;
    @Autowired
    ApiUserService apiUserService;
    @Autowired
    ApiAccountService apiAccountService;
    @Autowired
    ApiGameGoodsService apiGameGoodsService;
    @Autowired
    ApiGameOrderService apiGameOrderService;
    @Autowired
    ApiMachineService apiMachineService;


    private RedisUtil ru = RedisUtil.getRu();

    public static PropertiesLoader propertiesLoader = new PropertiesLoader("sysconfig.properties");


    @Override
    public ApiMessage init(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "registrationId");
        T_machinePO tMachinePO = daoMachine.selectByRegistrationId(dto.getString("registrationId"));
        checkMachine(tMachinePO);
        tMachinePO.setRegistration_id(dto.getString("registrationId"));
        Dto resDto = Dtos.newDto();
        resDto.put("machineId", tMachinePO.getId());
        resDto.put("machineName", tMachinePO.getMachine_name());
        //resDto.put("wsUrl", propertiesLoader.getProperty("ws_url"));
        String picUrl = "";
        if (SystemUtils.isEmpty(tMachinePO.getLogin_qr_img_url())) {
            try {
                picUrl = QiniuUploadFile.uploadGuagameQrCode(propertiesLoader.getProperty("game_login_url") + "?machineId=" + tMachinePO.getId());
            } catch (Exception e) {
                log.error("上传失败！");
            }
            tMachinePO.setLogin_qr_img_url(picUrl);
        }
        //保存信息
        tMachinePO.setOnline_status("1"); //在线
        tMachineDao.updateByKey(tMachinePO);
        resDto.put("loginUrl", tMachinePO.getLogin_qr_img_url());
        //获取游戏节目以及价格列表
        List<Dto> gameList = daoGame.getValidGameList();
        for (Dto gameDto : gameList) {
            List<Dto> prizeList = daoGamePrice.getValidGamePriceList(gameDto.getString("game_id"));
            gameDto.put("prizeList", prizeList);
        }
        resDto.put("gameList", gameList);
        resDto.put("bigRewardList",daoBigReward.queryList(Dtos.newDto()));

        //机器登录
        dto.put("machineId", tMachinePO.getId());
        machineLogin(dto);

        return ApiMessageUtil.success(resDto);
    }

    @Override
    public ApiMessage machineLogin(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "machineId");
        //机器码是否存在
        T_machinePO tMachinePO = getMachineById(dto.getString("machineId"));
        //redis保存
//        Map<String, String> map = new HashMap<String, String>();
//        map.put("sessionId", dto.getString("sessionId"));
//        ru.hmset("machine:ms_" + dto.getString("machineId"), map);
//        map.clear();
//        map.put("machineId", tMachinePO.getId());
//        ru.hmset("session:session_" + dto.getString("sessionId"), map);

        Map<String, String> map = new HashMap<String, String>();
        map.put("sessionId", tMachinePO.getRegistration_id());
        ru.hmset("machine:ms_" + dto.getString("machineId"), map);
        map.clear();
        map.put("machineId", tMachinePO.getId());
        ru.hmset("session:session_" + tMachinePO.getRegistration_id(), map);
        return ApiMessageUtil.success();
    }

    @Override
    public ApiMessage machineLogout(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "machineId");
        ru.hdel("machine:ms_" + dto.getString("machineId"), "sessionId");
        ru.hdel("machine:mu_" + dto.getString("machineId"), "userId");
        return ApiMessageUtil.success();
    }

    @Override
    public ApiMessage userLogin(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "machineId,userId");
        T_machinePO tMachinePO = getMachineById(dto.getString("machineId"));
        T_userPO tUserPO = apiUserService.getUserById(dto.getString("userId"));

//        String sessionId = ru.hmget("machine:ms_" + dto.getString("machineId"), "sessionId").get(0);
//        if (SystemUtils.isEmpty(sessionId)) {
//            throw new ApiException(ReqEnums.MACHINE_IS_NOT_LOGIN);
//        }
//        String machineId = ru.hmget("user:user_" + dto.getString("userId"), "machineId").get(0);
//        if (SystemUtils.isNotEmpty(machineId)) {
//            throw new ApiException(ReqEnums.MACHINE_USER_LOGIN_OTHER);
//        }
//        Map<String, String> map = new HashMap<String, String>();
//        map.put("machineId", dto.getString("machineId"));
//        ru.hmset("user:user_" + dto.getString("userId"), map);
//        String userId = ru.hmget("machine:mu_" + dto.getString("machineId"), "userId").get(0);
//        if (SystemUtils.isNotEmpty(userId)) {
//            throw new ApiException(ReqEnums.MACHINE_IS_USER_LOGIN);
//        }
//        map = new HashMap<String, String>();
//        map.put("sessionId", sessionId);
//        ru.hmset("machine:ms_" + dto.getString("machineId"), map);
//        map.clear();
//        map.put("userId", dto.getString("userId"));
//        ru.hmset("machine:mu_" + dto.getString("machineId"), map);
//
//        //初始化游戏状态
//        map.clear();
//        map.put("gameStatus", "0");
//        ru.hmset("game:gu_" + dto.getString("userId"), map);

        //保存登录记录
        saveLoginDetail(tUserPO.getId(), tMachinePO.getId(), 1);

        //发送到指定机器登录报文
        T_accountPO accountPO = daoAccount.selectByUserId(dto.getString("userId"));
        Dto resDto = Dtos.newDto();
        resDto.put("nickName", tUserPO.getNick_name());
        resDto.put("headImg", tUserPO.getHead_img());
        resDto.put("money", accountPO.getMoney());
        resDto.put("userId",tUserPO.getId());
        //todo 商品
        resDto.put("bagList", "");
        resDto.put("method", "userLogin");
        resDto.put("registrationId",tMachinePO.getRegistration_id());
        jpushToMachine(resDto);
        return ApiMessageUtil.success();
    }

    @Override
    public ApiMessage userLogout(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "machineId,userId");
        T_machinePO tMachinePO = getMachineById(dto.getString("machineId"));
//        String sessionId = ru.hmget("machine:ms_" + tMachinePO.getId(), "sessionId").get(0);
//        if (SystemUtils.isEmpty(sessionId)) {
//            throw new ApiException(ReqEnums.MACHINE_IS_NOT_LOGIN);
//        }
//        String userId = ru.hmget("machine:mu_" + tMachinePO.getId(), "userId").get(0);
//        if (SystemUtils.isEmpty(userId)) {
//            throw new ApiException(ReqEnums.MACHINE_IS_NOT_USER_LOGIN);
//        }

        //保存登录记录
        saveLoginDetail(dto.getString("userId"), tMachinePO.getId(), 2);
//        ru.hdel("machine:mu_" + tMachinePO.getId(), "userId");
//        ru.hdel("user:user_" + userId, "machineId");
//        ru.hdel("game:gu_" + userId, "gameStatus");


        Dto resDto = Dtos.newDto();
        resDto.put("method", "userLogout");
        resDto.put("registrationId",tMachinePO.getRegistration_id());
        jpushToMachine(resDto);
        return ApiMessageUtil.success();
    }

    @Override
    public ApiMessage getUserInfo(Dto dto) throws ApiException {
        return null;
    }

    @Override
    public void delAllSession(String sessionId) throws ApiException {
        String machineId = ru.hmget("session:session_" + sessionId, "machineId").get(0);
        if (SystemUtils.isNotEmpty(machineId)) {
            String userId = ru.hmget("machine:mu_" + machineId, "userId").get(0);
            if (SystemUtils.isNotEmpty(userId)) {
                ru.hdel("user:user_" + userId, "machineId");
                ru.hdel("machine:mu_" + machineId, "userId");
                ru.hdel("game:gu_" + userId, "gameStatus");

                //保存登录记录
                saveLoginDetail(userId, machineId, 2);
            }
            ru.hdel("machine:ms_" + machineId, "sessionId");
        }
        ru.hdel("session:session_" + sessionId, "machineId");
        return;
    }

    @Override
    public ApiMessage sendToMachineId(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "machineId,content");
        String sessionId = ru.hget("machine:ms_" + dto.getString("machineId"), "sessionId");
        if (isMachineLogin(dto.getString("machineId"))) {
//            WebSocketTools.sendToId(ApiMessageUtil.success((Dto) dto.get("content")), sessionId);
        } else {
            throw new ApiException(ReqEnums.MACHINE_IS_NOT_LOGIN);
        }
        return ApiMessageUtil.success();
    }

    @Override
    public ApiMessage createOrder(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "userId,machineId,prizeId");
        T_machinePO tMachinePO = getMachineById(dto.getString("machineId"));
        T_userPO tUserPO = apiUserService.getUserById(dto.getString("userId"));
        ApiMessage res = new ApiMessage();
        //判断机器用户是否登录
        //checkMachineAndUser(tUserPO,tMachinePO);
        //下单
        T_game_pricePO tGamePricePO = tGamePriceDao.selectByKey(dto.getString("prizeId"));
        dto.put("typeId", tGamePricePO.getOrder_type());
        dto.put("machineId", tMachinePO.getId());
        dto.put("machineName", tMachinePO.getMachine_name());
        dto.put("shopName", tShopDao.selectByKey(tMachinePO.getShop_id()).getShop_name());
        dto.put("sn", PrimaryGenerater.getInstance().next());
        //游戏状态
        Map<String, String> map = new HashMap<String, String>();
        map.put("gameStatus", "1");
        ru.hmset("game:gu_" + dto.getString("userId"), map);
        return apiOrderService.createOrder(dto);
    }



    @Override
    public ApiMessage orderPlusResult(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto, "userId,machineId,orderId");
        T_machinePO tMachinePO = getMachineById(dto.getString("machineId"));
        T_userPO tUserPO = apiUserService.getUserById(dto.getString("userId"));
        //判断机器用户是否登录
        checkMachineAndUser(tUserPO,tMachinePO);
         //订单加奖
        ApiMessage res =apiGameGoodsService.getMyGoodsList(dto);
        return ApiMessageUtil.success(res);
    }


    @Override
    public boolean isMachineLogin(String machineId) throws ApiException {
        String res = ru.hget("machine:ms_" + machineId, "sessionId");
        return SystemUtils.isNotEmpty(res);
    }

    @Override
    public boolean isUserLogin(String userId, String machineId) throws ApiException {
        String resMachineId = ru.hmget("user:user_" + userId, "machineId").get(0);
        if (SystemUtils.isEmpty(resMachineId)) {
            throw new ApiException(ReqEnums.USER_IS_NOT_LOGIN_MACHINE);
        } else if (!resMachineId.equals(machineId)) {
            throw new ApiException(ReqEnums.USER_IS_LOGIN_OTHER_MACHINE);
        }
        return resMachineId.equals(machineId);
    }


    @Override
    public T_machinePO getMachineById(String machineId) throws ApiException {
        T_machinePO t_machinePO = tMachineDao.selectByKey(machineId);
        checkMachine(t_machinePO);
        return t_machinePO;
    }


    @Override
    public void saveLoginDetail(String userId, String machineId, int status) throws ApiException {
        T_userPO tUserPO = apiUserService.getUserById(userId);
        T_machinePO tMachinePO = getMachineById(machineId);
        //保存登录信息
        tUserPO.setLogin_status(status == 1 ? "1" : "0");
        tUserPO.setMachine_id(machineId);
        tUserDao.updateByKey(tUserPO);
        //保存机器登录
        T_machine_loginPO tMachineLoginPO = new T_machine_loginPO();
        tMachineLoginPO.setId(SystemIdUtils.uuid());
        tMachineLoginPO.setUser_id(tUserPO.getId());
        tMachineLoginPO.setMachine_id(tMachinePO.getId());
        tMachineLoginPO.setShop_id(tMachineLoginPO.getShop_id());
        tMachineLoginPO.setShop_name(tShopDao.selectByKey(tMachinePO.getShop_id()).getShop_name());
        tMachineLoginPO.setMachine_name(tMachinePO.getMachine_name());
        tMachineLoginPO.setStatus(String.valueOf(status));
        tMachineLoginPO.setLogin_time(new Date());
        tMachineLoginPO.setCreate_time(new Date());
        tMachineLoginPO.setIs_valid("1");
        tMachineLoginDao.insert(tMachineLoginPO);
    }



    @Override
    public ApiMessage getMachineAndShopById(Dto dto) throws ApiException {
        Dto outDto = Dtos.newDto();
        T_machinePO t_machinePO = tMachineDao.selectByKey(dto.getString("machineId"));
        if (!SystemUtils.isEmpty(t_machinePO)) {
            T_shopPO shopPO = tShopDao.selectByKey(t_machinePO.getShop_id());
            outDto.put("shop_id", t_machinePO.getShop_id());
            outDto.put("shop_name", shopPO.getShop_name());
            outDto.put("machine_num", t_machinePO.getMachine_num());
            outDto.put("machine_name", t_machinePO.getMachine_name());
            outDto.put("machine_status", t_machinePO.getMachine_status());
            outDto.put("machine_type", t_machinePO.getMachine_type());
        }
        return ApiMessageUtil.success(outDto);
    }



    @Override
    public   void  jpushToUser(Dto dto) throws ApiException {
        T_userPO tUserPO=apiUserService.getUserById(dto.getString("'userId"));
        if ("1".equals(tUserPO.getLogin_status())){
            T_machinePO tMachinePO =getMachineById(tUserPO.getMachine_id());
            int res = 0;
            try {
                res = JpushClientUtil.sendToRegistrationId(tMachinePO.getRegistration_id(), dto.getString("method"),  dto.getString("method"), Des3Utils.encResponse(dto), "userLogin");
            } catch (Exception e) {
                log.error("推送"+dto.getString("method")+" 错误" + e.getMessage());
            }
            if (res == 0) {
                log.error("推送"+dto.getString("method")+"失败" + dto.toString());
            } else {
                log.info("推送"+dto.getString("method")+"成功" + dto.toString());
            }
        }
   }

    @Override
    public ApiMessage getMachineLoginStatus(Dto dto) throws ApiException {
        ApiUtils.checkParam(dto,"machineId");
        T_machine_loginPO tMachineLoginPO =daoMachineLogin.selectByMachineId(dto);
        Dto resDto=Dtos.newDto();
        if ("1".equals(tMachineLoginPO.getStatus())){
            //获取登录信息
            T_userPO tUserPO = apiUserService.getUserById(tMachineLoginPO.getUser_id());
            //发送到指定机器登录报文
            T_accountPO accountPO = daoAccount.selectByUserId(tMachineLoginPO.getUser_id());
            resDto.put("nickName", tUserPO.getNick_name());
            resDto.put("headImg", tUserPO.getHead_img());
            resDto.put("money", accountPO.getMoney());
        }
        resDto.put("status",tMachineLoginPO.getStatus());
        resDto.put("userId",tMachineLoginPO.getUser_id());
        return ApiMessageUtil.success(resDto);
    }

    public   void  jpushToMachine(Dto dto) throws ApiException {
            int res = 0;
            try {
                res = JpushClientUtil.sendToRegistrationId(dto.getString("registrationId"), dto.getString("method"),  dto.getString("method"), Des3Utils.encResponse(dto), "userLogin");
            } catch (Exception e) {
                log.error("推送"+dto.getString("method")+" 错误" + e.getMessage());
            }
            if (res == 0) {
                log.error("推送"+dto.getString("method")+"失败" + dto.toString());
            } else {
                log.info("推送"+dto.getString("method")+"成功" + dto.toString());
            }
      }






    private void checkMachine(T_machinePO t_machinePO) throws ApiException {
        if (SystemUtils.isEmpty(t_machinePO)) {
            throw new ApiException(ReqEnums.MACHINE_IS_NOT_EXSIT);
        } else if ("0".equals(t_machinePO.getIs_valid())) {
            throw new ApiException(ReqEnums.MACHINE_IS_NOT_EXSIT);
        } else if ("0".equals(t_machinePO.getMachine_status())) {
            throw new ApiException(ReqEnums.MACHINE_STATUS_UNDISTRIBUTED);
        } else if ("2".equals(t_machinePO.getMachine_status())) {
            throw new ApiException(ReqEnums.MACHINE_STATUS_BROKEN);
        }
    }

    private void checkMachineAndUser(T_userPO t_userPO, T_machinePO t_machinePO) throws ApiException {
        //1判断机器
        checkMachine(t_machinePO);
        //2用户判断

        //机器登录判断
        if (!isMachineLogin(t_machinePO.getId())) {
            throw new ApiException(ReqEnums.MACHINE_IS_NOT_LOGIN);
        }
        //用户机器登录关系判断
        isUserLogin(t_userPO.getId(), t_machinePO.getId());
    }


}
